home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / programm.ing / cpp114.zoo / src / token.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-01-27  |  18.4 KB  |  849 lines

  1.  
  2. /*---------------------------------------------------------------------*\
  3. |                                    |
  4. | CPP -- a stand-alone C preprocessor                    |
  5. | Copyright (c) 1993-95 Hacker Ltd.        Author: Scott Bigham    |
  6. |                                    |
  7. | Permission is granted to anyone to use this software for any purpose    |
  8. | on any computer system, and to redistribute it freely, with the    |
  9. | following restrictions:                        |
  10. | - No charge may be made other than reasonable charges for repro-    |
  11. |     duction.                                |
  12. | - Modified versions must be clearly marked as such.            |
  13. | - The author is not responsible for any harmful consequences of    |
  14. |     using this software, even if they result from defects therein.    |
  15. |                                    |
  16. | token.c -- transform raw input to preprocessor tokens            |
  17. \*---------------------------------------------------------------------*/
  18.  
  19. /*
  20.    There are (for better or worse) three interfaces to the tokenizing
  21.    mechanism, at increasing levels of abstraction.  _one_token() tokenizes
  22.    directly out of the input line buffer, and should generally only be used
  23.    while handling preprocessor directive lines.  token() pre-tokenizes an
  24.    entire line of input at a time and doles it out one token at a time.  Note
  25.    that tokens returned by token() may or may not have undergone macro
  26.    expansion; use it when you need access to pre-expanded input tokens.
  27.    exp_token() fully expands each token before returning it; this is usually
  28.    the best way to access input.
  29. */
  30.  
  31. #include <ctype.h>
  32. #include <stdlib.h>
  33. #include <stdio.h>
  34. #include <stddef.h>
  35. #include "global.h"
  36. #include "ztype.h"
  37. #include "alloc.h"
  38.  
  39. #define BASE10    1
  40. #define BASE8    2
  41. #define BASE16    3
  42.  
  43. #define GRANULARITY 256
  44.  
  45. extern char *next_c;
  46.  
  47. static int tok_flags = 0;
  48. static TokenP pushback_list;
  49. static int wrapped_string = 0;
  50.  
  51. /* mk_Token() -- allocate and initialize space for a Token */
  52. TokenP mk_Token()
  53. {
  54.   register TokenP T = alloc_Token();
  55.  
  56.   T->val = T->hashval = T->type = T->subtype = 0;
  57.   T->_txt.out_of_line = T->_ws.out_of_line = NULL;
  58.   T->flags = (INLINE_TXT | INLINE_WS);
  59.   T->_txt.in_line[0] = T->_ws.in_line[0] = '\0';
  60. #if 0            /* already done in alloc_Token() */
  61.   T->next = NULL;
  62. #endif
  63.   return T;
  64. }
  65.  
  66. /* clear_txt() -- clear the text space of a token */
  67. void clear_txt(T)
  68.   register TokenP T;
  69. {
  70.   if (!(T->flags & INLINE_TXT) && T->_txt.out_of_line)
  71.     free(T->_txt.out_of_line);
  72.   T->flags |= INLINE_TXT;
  73.   T->_txt.in_line[0] = '\0';
  74. }
  75.  
  76. /* clear_ws() -- clear the white space of a token */
  77. void clear_ws(T)
  78.   register TokenP T;
  79. {
  80.   if (!(T->flags & INLINE_WS) && T->_ws.out_of_line)
  81.     free(T->_ws.out_of_line);
  82.   T->flags |= INLINE_WS;
  83.   T->_ws.in_line[0] = '\0';
  84. }
  85.  
  86. /* set_txt() -- set the text of a token to |s|, copying if necessary,
  87.    and deleting the current text, if any */
  88. void set_txt(T, s)
  89.   register TokenP T;
  90.   register const char *s;
  91. {
  92.   if (!(T->flags & INLINE_TXT) && T->_txt.out_of_line)
  93.     free(T->_txt.out_of_line);
  94.   if (strlen(s) <= 7) {
  95.     T->flags |= INLINE_TXT;
  96.     strcpy(T->_txt.in_line, s);
  97.   } else {
  98.     T->flags &= ~INLINE_TXT;
  99.     T->_txt.out_of_line = strdup(s);
  100.   }
  101. }
  102.  
  103. /* set_txt_n() -- set the text of a token to the first |n| characters
  104.    of |s|, copying if necessary, and deleting the current text, if any */
  105. void set_txt_n(T, s, n)
  106.   register TokenP T;
  107.   register const char *s;
  108.   int n;
  109. {
  110.   if (!(T->flags & INLINE_TXT) && T->_txt.out_of_line)
  111.     free(T->_txt.out_of_line);
  112.   if (n <= 7) {
  113.     T->flags |= INLINE_TXT;
  114.     strncpy(T->_txt.in_line, s, n);
  115.     T->_txt.in_line[n] = '\0';
  116.   } else {
  117.     T->flags &= ~INLINE_TXT;
  118.     T->_txt.out_of_line = mallok(n + 1);
  119.     strncpy(T->_txt.out_of_line, s, n);
  120.     T->_txt.out_of_line[n] = '\0';
  121.   }
  122. }
  123.  
  124. /* set_ws() -- set the white space of a token to |s|, copying if
  125.    necessary, and deleting the current white space, if any */
  126. void set_ws(T, s)
  127.   register TokenP T;
  128.   register const char *s;
  129. {
  130.   if (!(T->flags & INLINE_WS) && T->_ws.out_of_line)
  131.     free(T->_ws.out_of_line);
  132.   if (strlen(s) <= 3) {
  133.     T->flags |= INLINE_WS;
  134.     strcpy(T->_ws.in_line, s);
  135.   } else {
  136.     T->flags &= ~INLINE_WS;
  137.     T->_ws.out_of_line = strdup(s);
  138.   }
  139. }
  140.  
  141. /* free_token() -- return an allocated Token to the free list */
  142. void free_token(T)
  143.   register TokenP T;
  144. {
  145.   T->next = NULL;
  146.   free_tlist(T);
  147. }
  148.  
  149. /* free_tlist() -- return a list of Token's to the free list */
  150. void free_tlist(T)
  151.   register TokenP T;
  152. {
  153.   register TokenP T1;
  154.  
  155.   for (; T; T = T1) {
  156.     T1 = T->next;
  157.     clear_txt(T);
  158.     clear_ws(T);
  159.     dealloc_Token(T);
  160.   }
  161. }
  162.  
  163. /*
  164.    copy_token() -- return a new Token that is a duplicate of the given token
  165. */
  166. TokenP copy_token(T1)
  167.   register TokenP T1;
  168. {
  169.   register TokenP T2 = mk_Token();
  170.  
  171.   *T2 = *T1;
  172.   if (!(T1->flags & INLINE_WS))
  173.     T2->_ws.out_of_line = strdup(T1->_ws.out_of_line);
  174.   if (!(T1->flags & INLINE_TXT))
  175.     T2->_txt.out_of_line = strdup(T1->_txt.out_of_line);
  176.   T2->next = NULL;
  177.   return T2;
  178. }
  179.  
  180. /* copy_tlist() -- create a duplicate of a list of Token's */
  181. TokenP copy_tlist(T1)
  182.   register TokenP T1;
  183. {
  184.   Token head;
  185.   register TokenP T2 = &head;
  186.  
  187.   for (T2->next = NULL; T1; T1 = T1->next, T2 = T2->next)
  188.     T2->next = copy_token(T1);
  189.   return head.next;
  190. }
  191.  
  192. /* tok_shutdown() -- free all space allocated for Token's */
  193. void tok_shutdown()
  194. {
  195. #ifdef DEBUG        /* explicitly clean up, to check for memory leaks */
  196. #if 0
  197.   register TokenP T, T1;
  198.   register int i;
  199.  
  200.   for (T1 = T = tok_blocks; T; T = T1) {
  201.     T1 = T->next;
  202.     for (i = 1; i < GRANULARITY; i++) {
  203.       if (T[i].flags & IN_USE) {
  204.     fprintf(stderr, "@@@ Token not freed:  ");
  205.     dump_token(&T[i]);
  206.     fputc('\n', stderr);
  207.       }
  208.       clear_txt(&T[i]);
  209.       clear_ws(&T[i]);
  210.     }
  211.     free(T);
  212.   }
  213.   fprintf(stderr, "%d total blocks allocated\n", num_blocks);
  214. #else /* 0 */
  215.   cleanup_Token();
  216. #endif /* 0 */
  217. #endif
  218. }
  219.  
  220. /*
  221.    push_tlist() -- "un-read" the list of Token's |T|; token() will return all
  222.    of these tokens in order before reading another token from the input file
  223. */
  224. void push_tlist(T)
  225.   register TokenP T;
  226. {
  227.   register TokenP t;
  228.  
  229.   if (!T)
  230.     return;
  231.   t = T;
  232.   while (t->next)
  233.     t = t->next;
  234.   t->next = pushback_list;
  235.   pushback_list = T;
  236. }
  237.  
  238. /* mk_eof() -- makes and returns an EOF_ token */
  239. static TokenP mk_eof()
  240. {
  241.   register TokenP T = mk_Token();
  242.  
  243.   T->type = EOF_;
  244.   T->flags |= INLINE_TXT | INLINE_WS;
  245.   T->_ws.in_line[0] = T->_txt.in_line[0] = '\0';
  246.   return T;
  247. }
  248.  
  249. /*
  250.    mk_stopper() -- makes and returns a STOP token.  See expand_tlist() for
  251.    further information.
  252. */
  253. TokenP mk_stopper()
  254. {
  255.   register TokenP T = mk_Token();
  256.  
  257.   T->type = STOP;
  258.   T->flags |= INLINE_TXT | INLINE_WS;
  259.   T->_ws.in_line[0] = T->_txt.in_line[0] = '\0';
  260.   return T;
  261. }
  262.  
  263. /*
  264.    mk_unmarker() -- makes and returns a special token that informs the
  265.    tokenizer to unmark the macro text associated with token |T|.  See
  266.    expand() for further information.
  267. */
  268. TokenP mk_unmarker(T)
  269.   register TokenP T;
  270. {
  271.   register TokenP T1 = copy_token(T);
  272.  
  273.   T1->type = UNMARK;
  274.   T->flags |= INLINE_TXT | INLINE_WS;
  275.   T->_ws.in_line[0] = T->_txt.in_line[0] = '\0';
  276.   return T1;
  277. }
  278.  
  279. /*
  280.    mk_printable() -- makes and returns an untyped token with an
  281.    arbitrary text body, for purposes of printing directly via
  282.    print_token().
  283. */
  284.  
  285. TokenP mk_printable(s)
  286.   const char *s;
  287. {
  288.   register TokenP T = mk_Token();
  289.  
  290.   T->type = DONT_CARE;
  291.   set_ws(T, " ");
  292.   set_txt(T, s);
  293.   return T;
  294. }
  295.  
  296. /* flush_tokenizer() -- discard all Tokens pushed back by push_tlist() */
  297. void flush_tokenizer()
  298. {
  299.   free_tlist(pushback_list);
  300.   pushback_list = NULL;
  301. }
  302.  
  303. /*
  304.    pp_number_check() -- check that the token between |s| and |s_end|
  305.    conforms strictly to the grammar for preprocessing numbers listed in
  306.    ANSI/ISO 6.1.8
  307. */
  308. static void pp_number_check(s, s_end)
  309.   register char *s;
  310.   char *s_end;
  311. {
  312.   char *s_begin = s;
  313.  
  314.   if (*s == '.')
  315.     s++;
  316.   for (s++; ; s++) {
  317.     if ((*s == 'e' || *s == 'E') && (s[1] == '-' || s[1] == '+')) {
  318.       s++;
  319.       continue;
  320.     }
  321.     if (is_ctok(*s))
  322.       continue;
  323.     if (*s == '.')
  324.       continue;
  325.     break;
  326.   }
  327.   if (s != s_end) {
  328.     warning("(pedantic) Preprocessor token `%.*s' is not a syntactic token",
  329.         (int)(s - s_begin), s_begin);
  330.     message("Insert whitespace after `%.*s'", (int)(s_end - s_begin),
  331.         s_begin);
  332.   }
  333. }
  334.  
  335. /*
  336.    number() -- copies from |s| into the token |T| a string of characters
  337.    denoting an integer or floating-point constant.  Returns a pointer to the
  338.    first uncopied character.
  339. */
  340. static char *number(s, T)
  341.   register char *s;
  342.   register TokenP T;
  343. {
  344.   int numtype = BASE10, fpflag = 0;
  345.   char *t, *s_begin = s;
  346.  
  347.   T->type = NUMBER;
  348.   if (*s == '0') {
  349.     /* check for octal or hexadecimal constant */
  350.     if ((s[1] == 'x' || s[1] == 'X') && isxdigit(s[2])) {
  351.       numtype = BASE16;
  352.       T->flags |= UNS_VAL;
  353.     } else if (is_octal(s[1])) {
  354.       numtype = BASE8;
  355.       T->flags |= UNS_VAL;
  356.     }
  357.   }
  358.   T->val = strtol(s, &t, 0);
  359.   s = t;
  360.   if (numtype != BASE10 || is_isuff(*s)) {
  361.  
  362.     /*
  363.        if we're not in base 10, or the next characters are integer constant
  364.        suffixes, this can't be a floating-point constant
  365.     */
  366.     while (is_isuff(*s)) {
  367.       if (*s == 'u' || *s == 'U')
  368.     T->flags |= UNS_VAL;
  369.       s++;
  370.     }
  371.     if (pedantic)
  372.       pp_number_check(s_begin, s);
  373.     return s;
  374.   }
  375.   /* check to see if the number is actually floating point */
  376.   if (*s == '.') {
  377.     fpflag = 1;
  378.     do
  379.       s++;
  380.     while (isdigit(*s));
  381.   }
  382.   if (*s == 'e' || *s == 'E') {
  383.     register char *u = s;
  384.  
  385.     u++;
  386.     if (*u == '-' || *u == '+')
  387.       u++;
  388.     if (isdigit(*u)) {
  389.       fpflag = 1;
  390.       do
  391.     u++;
  392.       while (isdigit(*u));
  393.       s = u;
  394.     }
  395.   }
  396.   if (fpflag) {
  397.     T->type = FP_NUM;
  398.     if (is_fsuff(*s))
  399.       s++;
  400.   }
  401.   if (pedantic)
  402.     pp_number_check(s_begin, s);
  403.   return s;
  404. }
  405.  
  406. /*
  407.    char_constant() -- copy from |s| into the token |T| a string of characters
  408.    denoting a character constant.  We do not translate escape sequences at
  409.    this point, though we might need to
  410. */
  411. static char *char_constant(s, T)
  412.   register char *s;
  413.   register TokenP T;
  414. {
  415.   T->type = CHAR_CON;
  416.   for (; *s; s++) {
  417.     if (*s == '\'')
  418.       return s + 1;
  419.     if (*s == '\\')
  420.       s++;
  421.   }
  422.   error("unterminated character constant");
  423.   return s;
  424. }
  425.  
  426. /*
  427.    string_literal() -- copy from |s| into the token |T| a string of
  428.    characters denoting a string literal.  We do not translate escape
  429.    sequences at this point, though we might need to
  430. */
  431. static char *string_literal(s, T)
  432.   register char *s;
  433.   register TokenP T;
  434. {
  435.   T->type = STR_CON;
  436.   for (; *s; s++) {
  437.     if (*s == '"') {
  438.       wrapped_string = 0;
  439.       return s + 1;
  440.     }
  441.     if (*s == '\\')
  442.       s++;
  443.   }
  444.   if (gcc_strings)
  445.     wrapped_string = 1;
  446.   else
  447.     error("unterminated string literal");
  448.   return s;
  449. }
  450.  
  451. /*
  452.    include_name() -- copy from |s| into the token |T| a string of characters
  453.    denoting an #include file specifier enclosed in <>. |s| points to the
  454.    character after the '>'.
  455. */
  456. static char *include_name(s, T)
  457.   register char *s;
  458.   register TokenP T;
  459. {
  460.   T->type = INC_NAM;
  461.   for (; *s; s++) {
  462.     if (*s == '>')
  463.       return s + 1;
  464.   }
  465.   error("unterminated include file name");
  466.   return s;
  467. }
  468.  
  469. /* set_mode() -- set the tokenizer flags to |m| */
  470. void set_mode(m)
  471.   int m;
  472. {
  473.   tok_flags = m;
  474. }
  475.  
  476. /*
  477.    change_mode() -- twiddle the tokenizer flags; in particular, set the flags
  478.    specified in |raise| and clear the flags specified in |lower|
  479. */
  480. void change_mode(raise, lower)
  481.   int raise, lower;
  482. {
  483.   tok_flags |= raise;
  484.   tok_flags &= (~lower);
  485. }
  486.  
  487. /* get_mode() -- return the current value of the tokenizer flags */
  488. int get_mode()
  489. {
  490.   return tok_flags;
  491. }
  492.  
  493. /*
  494.    xlate_token() -- determines the type of the next preprocessor token in the
  495.    string pointed to by |s|.  Information about the token found is placed in
  496.    the Token |T|.  Returns a pointer to the first character not in the token
  497.    read.
  498. */
  499. static char *xlate_token(s, T)
  500.   register char *s;
  501.   register TokenP T;
  502. {
  503.   if (wrapped_string)
  504.     return string_literal(s, T);
  505.  
  506.   if (is_ctoks(*s)) {
  507.     char *t;
  508.  
  509.     T->hashval = hash_id(s, &t);
  510.     T->type = ID;
  511.     return t;
  512.   }
  513.  
  514.   if (isdigit(*s))
  515.     return number(s, T);
  516.  
  517.   switch (*s++) {
  518.     case '.':
  519.       T->subtype = '.';
  520.       if (*s == '.' && s[1] == '.') {
  521.     s += 2;
  522.     T->type = DONT_CARE;
  523.       } else if (isdigit(*s))
  524.     s = number(s - 1, T);
  525.       else
  526.     T->type = DONT_CARE;
  527.       break;
  528.     case '#':
  529.       if (*s == '#') {
  530.     s++;
  531.     T->type = TOK_CAT;
  532.       } else
  533.     T->type = POUND;
  534.       break;
  535.     case '&':
  536.       T->subtype = '&';
  537.       if (*s == '&') {
  538.     s++;
  539.     T->type = L_AND_OP;
  540.       } else if (*s == '=') {
  541.     s++;
  542.     T->type = DONT_CARE;
  543.       } else
  544.     T->type = B_AND_OP;
  545.       break;
  546.     case '|':
  547.       T->subtype = '|';
  548.       if (*s == '|') {
  549.     s++;
  550.     T->type = L_OR_OP;
  551.       } else if (*s == '=') {
  552.     s++;
  553.     T->type = DONT_CARE;
  554.       } else
  555.     T->type = B_OR_OP;
  556.       break;
  557.     case '+':
  558.       T->subtype = '+';
  559.       if (*s == s[-1] || *s == '=') {
  560.     s++;
  561.     T->type = DONT_CARE;
  562.       } else
  563.     T->type = ADD_OP;
  564.       break;
  565.     case '~':
  566.       T->type = UNARY_OP;
  567.       T->subtype = '~';
  568.       break;
  569.     case ',':
  570.       T->type = COMMA;
  571.       T->subtype = ',';
  572.       break;
  573.     case '(':
  574.       T->type = LPAREN;
  575.       T->subtype = '(';
  576.       break;
  577.     case ')':
  578.       T->type = RPAREN;
  579.       T->subtype = ')';
  580.       break;
  581.     case '!':
  582.       T->subtype = '!';
  583.       if (*s == '=') {
  584.     s++;
  585.     T->type = EQ_OP;
  586.       } else
  587.     T->type = UNARY_OP;
  588.       break;
  589.     case '=':
  590.       T->subtype = '=';
  591.       if (*s == '=') {
  592.     s++;
  593.     T->type = EQ_OP;
  594.       } else
  595.     T->type = DONT_CARE;
  596.       break;
  597.     case '*':
  598.     case '/':
  599.     case '%':
  600.       T->subtype = s[-1];
  601.       if (*s == '=') {
  602.     s++;
  603.     T->type = DONT_CARE;
  604.       } else
  605.     T->type = MUL_OP;
  606.       break;
  607.     case '^':
  608.       T->subtype = '^';
  609.       if (*s == '=') {
  610.     s++;
  611.     T->type = DONT_CARE;
  612.       } else
  613.     T->type = B_XOR_OP;
  614.       break;
  615.     case '-':
  616.       T->subtype = '-';
  617.       if (*s == '-' || *s == '=' || *s == '>') {
  618.     s++;
  619.     T->type = DONT_CARE;
  620.       } else
  621.     T->type = ADD_OP;
  622.       break;
  623.     case '<':
  624.       if (tok_flags & INCLUDE_LINE) {
  625.     s = include_name(s, T);
  626.     break;
  627.       }
  628.       /* else fall through */
  629.     case '>':
  630.       T->subtype = s[-1];
  631.       T->type = REL_OP;
  632.       if (*s == s[-1]) {
  633.     s++;
  634.     T->type = SHIFT_OP;
  635.       }
  636.       if (*s == '=') {
  637.     s++;
  638.     if (T->type == REL_OP)
  639.       T->subtype = (T->subtype == '<' ? '(' : ')');
  640.     else
  641.       T->type = DONT_CARE;
  642.       }
  643.       break;
  644.     case '\'':
  645.       s = char_constant(s, T);
  646.       break;
  647.     case '"':
  648.       s = string_literal(s, T);
  649.       break;
  650.     case '[':
  651.     case ']':
  652.     case '{':
  653.     case '}':
  654.     case ';':
  655.     case ':':
  656.     case '?':
  657.       T->type = DONT_CARE;
  658.       break;
  659.     default:
  660.       T->type = UNKNOWN;
  661.   }
  662.   return s;
  663. }
  664.  
  665. /* print_token() -- write token |T| to the output file */
  666. void print_token(T)
  667.   register TokenP T;
  668. {
  669.   if (in_config_file)
  670.     return;
  671.   if (T->type == STOP)
  672.     bugchk("STOP token in output stream?");
  673.   fputs(token_ws(T), outf);
  674.   fputs(token_txt(T), outf);
  675.   if (T->flags & TRAIL_SPC)
  676.     fputc(' ', outf);
  677. }
  678.  
  679. /*
  680.    merge_tokens() -- Perform token pasting on Token's |T1| and |T2|. Returns
  681.    the resulting token.
  682. */
  683. TokenP merge_tokens(T1, T2)
  684.   register TokenP T1, T2;
  685. {
  686.   register TokenP T = mk_Token();
  687.   register char *t;
  688.  
  689.   set_ws(T, token_ws(T1));
  690.   t = mallok(strlen(token_txt(T1)) + strlen(token_txt(T2)) + 1);
  691.   strcpy(t, token_txt(T1));
  692.   strcat(t, token_txt(T2));
  693.   set_txt(T, t);
  694.   free(t);
  695.   t = xlate_token(token_txt(T), T);
  696.   if (*t != '\0') {
  697.     if (w_bad_concat)
  698.       warning("Invalid token \"%s\" created by concatenation",
  699.           token_txt(T));
  700.     T->type = UNKNOWN;
  701.   }
  702.   return T;
  703. }
  704.  
  705. TokenP _one_token()
  706. {
  707.   register TokenP T = mk_Token();
  708.   register char *s = next_c, *t, *u;
  709.   int n;
  710.  
  711.   t = suck_ws(s, T);
  712.   if (!t || !*t) {
  713.     set_txt(T, "\n");
  714.     T->type = EOL;
  715.     T->subtype = '\n';
  716.     next_c = t;
  717.     return T;
  718.   }
  719.   u = xlate_token(t, T);
  720.   n = (int)(u - t);
  721.   if (T->type == UNKNOWN && w_bad_chars)
  722.     error("Unrecognized character 0x%02x='%c'", *t, *t);
  723.   set_txt_n(T, t, n);
  724.   next_c = u;
  725.   return T;
  726. }
  727.  
  728. void _tokenize_line()
  729. {
  730.   Token head;
  731.   register TokenP T = &head;
  732.  
  733.   head.next = NULL;
  734.   do {
  735.     T = T->next = _one_token();
  736.   } while (T->type != EOL);
  737.   push_tlist(head.next);
  738. }
  739.  
  740. TokenP token()
  741. {
  742.   register TokenP T;
  743.   register char *s;
  744.  
  745.   while (pushback_list) {
  746.     T = pushback_list;
  747.     pushback_list = T->next;
  748.     T->next = NULL;
  749.     if (T->type == UNMARK) {
  750.       Macro *M;
  751.  
  752.       M = lookup(token_txt(T), T->hashval);
  753.       if (!M)
  754.     bugchk("UNMARK on non-macro token %s", token_txt(T));
  755.       if (!(M->flags & MARKED))
  756.     bugchk("UNMARK on unmarked macro %s", token_txt(T));
  757.       M->flags ^= MARKED;
  758.       free_token(T);
  759.       continue;
  760.     } else {
  761.       return T;
  762.     }
  763.   }
  764.  
  765.   /*
  766.      if we get to here, the pushback list is empty, and we need to read in
  767.      another line
  768.   */
  769.   next_c = s = getline();
  770.   if (!s)
  771.     return mk_eof();
  772.   T = _one_token();
  773.   if (T->type == EOL) {
  774.     return T;
  775.   }
  776.   /*
  777.      If the line is a preprocessor directive, don't pre-tokenize the
  778.      rest of the line, as we need it in "raw" form.  If the line is not
  779.      a preprocessor directive and we're in the false branch of an #if
  780.      conditional, don't bother pre-tokenizing the line, because it will
  781.      just get thrown away (Note that we can't do this in the presence of
  782.      -fimplicit-newlines, because we need to know if the last token on
  783.      the line is an unterminated string).  If we're in the middle of
  784.      reading an argument of a parametrized macro, preprocessor
  785.      directives get trodden on anyway, so go ahead and pre-tokenize.
  786.   */
  787.   if ((T->type != POUND && (cond_true() || gcc_strings)) ||
  788.       (get_mode() & SLURP))
  789.     _tokenize_line();
  790.   return T;
  791. }
  792.  
  793. TokenP exp_token()
  794. {
  795.   register TokenP T = token();
  796.   register Macro *M;
  797.  
  798.   if (T->type == ID && !(T->flags & BLUEPAINT) &&
  799.       (M = lookup(token_txt(T), T->hashval))) {
  800.     expand(T, M);
  801.     free_token(T);
  802.     return exp_token();
  803.   } else
  804.     return T;
  805. }
  806.  
  807. #ifdef DEBUG
  808.  
  809. /*
  810.    debugging routines to display tokens in internal format
  811. */
  812.  
  813. void dump_token(T)
  814.   TokenP T;
  815. {
  816.   static char *type_names[] =
  817.   {"<<< ERROR >>>", "UNKNOWN", "DONT_CARE",
  818.    "EOL", "NUMBER", "FP_NUM", "ID", "STR_CON", "CHAR_CON", "UNARY_OP",
  819.    "MUL_OP", "ADD_OP", "SHIFT_OP", "REL_OP", "EQ_OP", "B_AND_OP",
  820.    "B_XOR_OP", "B_OR_OP", "L_AND_OP", "L_OR_OP", "LPAREN", "RPAREN",
  821.    "COMMA", "INC_NAM", "POUND", "TOK_CAT", "MACRO_ARG", "EOF_", "STOP",
  822.    "UNMARK"
  823.   };
  824.  
  825.   fprintf(stderr, "[%s, '%c', \"%s\", \"%s\", %ld, %x]@%p",
  826.       type_names[T->type], (T->subtype ? T->subtype : ' '),
  827.       (token_ws(T) ? token_ws(T) : "(null)"),
  828.       (token_txt(T) ? token_txt(T) : "(null)"),
  829.       T->val, T->flags, (void *)T
  830.       );
  831. }
  832.  
  833. void dump_tlist(T)
  834.   TokenP T;
  835. {
  836.   while (T) {
  837.     dump_token(T);
  838.     fputc('\n', stderr);
  839.     T = T->next;
  840.   }
  841. }
  842.  
  843. void dump_pushback()
  844. {
  845.   dump_tlist(pushback_list);
  846. }
  847.  
  848. #endif /* DEBUG */
  849.